package com.zyplayer.doc.manage.framework.SchedulerTask;

import cn.hutool.core.date.StopWatch;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.zyplayer.doc.data.repository.manage.entity.WikiPage;
import com.zyplayer.doc.data.repository.manage.entity.WikiPageContent;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageContentMapper;
import com.zyplayer.doc.data.repository.manage.mapper.WikiPageMapper;
import com.zyplayer.doc.git.service.GitServiceImpl;
import com.zyplayer.doc.git.service.HtmlConvertToMarkdownImpl;
import com.zyplayer.doc.git.utils.DocUtil;
import com.zyplayer.doc.git.utils.FilesUtils;
import com.zyplayer.doc.git.utils.ZipCreator;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.quartz.CronExpression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class HtmlConvertToMdSchedulerTask {

    private static final Logger logger = LoggerFactory.getLogger(HtmlConvertToMdSchedulerTask.class);

    private final HtmlConvertToMarkdownImpl htmlConvertToMdService;

    private final WikiPageContentMapper wikiPageContentMapper;

    private final WikiPageMapper wikiPageMapper;

    private final GitServiceImpl gitService;

    @Value("${zyplayer.doc.manage.enable.wiki:false}")
    private boolean isEnableWiki;

    @Value("${docsify.enable:false}")
    private boolean docsifyIsEnable;

    @Value("${zyplayer.doc.wiki.file-filter-list:}")
    private List<String> fileFilterList;

    @Value("${docsify.config.root-path:}")
    private String rootPath;

    @Value("${docsify.config.sidebar-file-path:}")
    private String sidebarFilePath;

    @Value("${package.enable:false}")
    private boolean packageIsEnable;

    @Value("${package.zip.default-file-path:}")
    private String packageDefaultFilePath;

    @Value("${zyplayer.doc.wiki.resource-url:}")
    private String resourceUri;

    @Value("${zyplayer.doc.wiki.generator-md-cron:0 0 1 * * ?}")
    private String generatorMdCron;

    @Value("${zyplayer.doc.wiki.git-local-path:}")
    private String gitLocalPath;


    @Scheduled(cron = "${zyplayer.doc.wiki.generator-md-cron:0 0 1 * * ?}")
    @Async("threadPoolExecutor")
    public void generatorMdTask() {
        if (Boolean.FALSE.equals(isEnableWiki)) {
            logger.info("WIKI模块没有开启。如果需要生成MD文件和备份文件，需要开启‘zyplayer.doc.manage.enable.wiki’配置.");
            return;
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("定时任务: Html转markdown文件");
        List<WikiPageContent> wikiPageContents = wikiPageContentMapper.selectList(new QueryWrapper<>());
        ForkJoinPool forkJoinPool = new ForkJoinPool(2);
        try {
            if (packageIsEnable && StringUtils.isNotBlank(gitLocalPath) && StringUtils.isNotBlank(packageDefaultFilePath)) {
                //上一个版本打包
                ZipCreator.createZip(gitLocalPath, packageDefaultFilePath, fileFilterList);
            }

            //清空gitLocalPath存放目录
            FilesUtils.delAllFile(gitLocalPath, fileFilterList);
            //pageId map pageContent
            for (List<WikiPageContent> pageContents : Lists.partition(wikiPageContents, 500)) {
                LambdaQueryWrapper<WikiPage> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(WikiPage::getId, pageContents.stream()
                        .map(WikiPageContent::getPageId).collect(Collectors.toList())
                );
                queryWrapper.eq(WikiPage::getDelFlag, 0);

                Map<Long, String> pageIdMapContent =
                        pageContents.stream().collect(Collectors.toMap(WikiPageContent::getPageId, WikiPageContent::getContent));
                List<WikiPage> wikiPages = wikiPageMapper.selectList(queryWrapper);
                forkJoinPool.submit(() -> {
                    wikiPages.parallelStream().forEach(wikiPage -> {
                        if (Objects.nonNull(wikiPage)) {
                            try {
                                htmlConvertToMdService.convertToMd(gitLocalPath, wikiPage.getName(),
                                        pageIdMapContent.get(wikiPage.getId()), resourceUri,
                                        StandardCharsets.UTF_8.toString(), wikiPage.getEditorType());
                            } catch (Exception error) {
                                logger.info("generatorMdTask error: {}  {}", error.getMessage(), wikiPage);
                            }
                        }
                    });
                }).get();
            }

        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
        stopWatch.stop();
        logger.info("generatorMdTask: {}  ns:  {}", stopWatch, stopWatch.prettyPrint());

        if (docsifyIsEnable && StringUtils.isNotBlank(rootPath) && StringUtils.isNotBlank(sidebarFilePath)) {
            //生成_sidebar.md文件
            try {
                DocUtil.autoGeneratorSidebarDir(rootPath, sidebarFilePath, fileFilterList);
            } catch (Exception e) {
                logger.info(e.getMessage());
            }
        }

//        --------push
        try {
            CronExpression cronExpression = new CronExpression(generatorMdCron);
            TimeZone timeZone = cronExpression.getTimeZone();
            Calendar instance = Calendar.getInstance(timeZone);
            Date time = instance.getTime();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String formattedDate = sdf.format(time);

            gitService.oneClickPush("自动备份执行时间: " + formattedDate);
        } catch (GitAPIException e) {
            logger.info("Git备份数据失败：{}", e.getMessage());
            throw new RuntimeException(e);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }

}
